﻿using Entity;
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;

namespace Repository
{
    public class Context : DbContext
    {
        public Context()
            : base("Checker")
        {

        }


        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {

        }
        public DbSet<ChatDiary> ChatDiaries { get; set; }
        public DbSet<Diary> Diaries { get; set; }
        public DbSet<Games> Games { get; set; }
        public DbSet<Users> Users { get; set; }
        public DbSet<Table> Tables { get; set; }
    }

    public class Repository
    {
        private static List<string> WaitingUsers;
        private static int guestNumber = 1000;
        private static int gameNumber = 0;

        public Repository()
        {
            WaitingUsers = new List<string>();
             using (var ctx = new Context())
             {
                 try
                 {
                     var users = ctx.Users.ToList();
                     if(users==null)
                     {
                         MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
                         md5.ComputeHash(ASCIIEncoding.ASCII.GetBytes("admin"));
                         byte[] md5hash = md5.Hash;
                         StringBuilder str = new StringBuilder();
                         for (int i = 0; i < md5hash.Length; i++)
                         {
                             str.Append(md5hash[i].ToString("x2"));
                         }

                         Users user = new Users() { UserId = "Admin", Password = str.ToString(), Draw = 0, ELO = 0, Email = "admin@admin.com", Level = 0, LoggedIn = false, Loss = 0, Win = 0 };

                         ctx.Users.Add(user);
                         md5.ComputeHash(ASCIIEncoding.ASCII.GetBytes("dummy"));
                         md5hash = md5.Hash;
                         str = new StringBuilder();
                         for (int i = 0; i < md5hash.Length; i++)
                         {
                             str.Append(md5hash[i].ToString("x2"));
                         }

                         Users dummy1 = new Users() { UserId = "Dummy1", Password = str.ToString(), Draw = 0, ELO = 0, Email = "dummy1@dummy.com", Level = 0, LoggedIn = false, Loss = 0, Win = 0 };
                         ctx.Users.Add(dummy1);
                         Users dummy2 = new Users() { UserId = "Dummy2", Password = str.ToString(), Draw = 0, ELO = 0, Email = "dummy2@dummy.com", Level = 0, LoggedIn = true, Loss = 0, Win = 0 };
                         ctx.Users.Add(dummy2);
                         Users dummy3 = new Users() { UserId = "Dummy3", Password = str.ToString(), Draw = 0, ELO = 0, Email = "dummy3@dummy.com", Level = 0, LoggedIn = false, Loss = 0, Win = 0 };
                         ctx.Users.Add(dummy3);
                         Users dummy4 = new Users() { UserId = "Dummy4", Password = str.ToString(), Draw = 0, ELO = 0, Email = "dummy4@dummy.com", Level = 0, LoggedIn = true, Loss = 0, Win = 0 };
                         ctx.Users.Add(dummy4);
                         Users dummy5 = new Users() { UserId = "Dummy5", Password = str.ToString(), Draw = 0, ELO = 0, Email = "dummy5@dummy.com", Level = 0, LoggedIn = false, Loss = 0, Win = 0 };
                         ctx.Users.Add(dummy5);
                         Users dummy6 = new Users() { UserId = "Dummy6", Password = str.ToString(), Draw = 0, ELO = 0, Email = "dummy6@dummy.com", Level = 0, LoggedIn = true, Loss = 0, Win = 0 };
                         ctx.Users.Add(dummy6);
                         Users dummy7 = new Users() { UserId = "Dummy7", Password = str.ToString(), Draw = 0, ELO = 0, Email = "dummy7@dummy.com", Level = 0, LoggedIn = false, Loss = 0, Win = 0 };
                         ctx.Users.Add(dummy7);
                         Users dummy8 = new Users() { UserId = "Dummy8", Password = str.ToString(), Draw = 0, ELO = 0, Email = "dummy8@dummy.com", Level = 0, LoggedIn = true, Loss = 0, Win = 0 };
                         ctx.Users.Add(dummy8);

                         Games game = new Games() { GameId = "1", LastMove = DateTime.Now, PlayerOne = dummy1, PlayerTwo = dummy2, Status = 1, FirstPlayerTurn = true };
                         Games game2 = new Games() { GameId = "2", LastMove = DateTime.Now, PlayerOne = dummy3, PlayerTwo = dummy4, Status = 1, FirstPlayerTurn = true };
                         Games game3 = new Games() { GameId = "3", LastMove = DateTime.Now, PlayerOne = dummy5, PlayerTwo = dummy6, Status = 1, FirstPlayerTurn = true };
                         Games game4 = new Games() { GameId = "4", LastMove = DateTime.Now, PlayerOne = dummy7, PlayerTwo = dummy8, Status = 1, FirstPlayerTurn = true };
                         ctx.Games.Add(game);
                         ctx.Games.Add(game2);
                         ctx.Games.Add(game3);
                         ctx.Games.Add(game4);
                         ctx.SaveChanges();
                         NewEmptyGame("1");
                         BeatGame("2");
                         KingGame("3");
                         WinGame("4");
                     }
                 }
                 catch (Exception)
                 {
                     
                 }
                 

             }
             

             
            using (var ctx = new Context())
            {
                var result = ctx.Users.Where(l => (l.UserId.StartsWith("Guest")));
                var results = result.OrderByDescending(l => l.UserId).ToList();
                if (results.Count() != 0)
                {
                    guestNumber = Convert.ToInt32((results.ElementAt(0).UserId.Split('_'))[1]) + 1;
                }
                var resultGame = ctx.Games.OrderByDescending(l => l.GameId).ToList();
                if (resultGame.Count() != 0)
                {
                    gameNumber = Convert.ToInt32(resultGame.Count);
                }
            }

        }

        private void NewEmptyGame(string t_id)
        {
            using (var ctx = new Context())
            {
                Table table = new Table() { TableId = t_id, Position = "A1", Value = -1 };
                Table table2 = new Table() { TableId = t_id, Position = "A3", Value = -1 };
                Table table3 = new Table() { TableId = t_id, Position = "C1", Value = -1 };
                Table table4 = new Table() { TableId = t_id, Position = "C3", Value = -1 };

                Table table5 = new Table() { TableId = t_id, Position = "B2", Value = -1 };
                Table table6 = new Table() { TableId = t_id, Position = "D2", Value = -1 };
                Table table7 = new Table() { TableId = t_id, Position = "F2", Value = -1 };
                Table table8 = new Table() { TableId = t_id, Position = "H2", Value = -1 };

                Table table9 = new Table() { TableId = t_id, Position = "E1", Value = -1 };
                Table table10 = new Table() { TableId = t_id, Position = "E3", Value = -1 };
                Table table11 = new Table() { TableId = t_id, Position = "G1", Value = -1 };
                Table table12 = new Table() { TableId = t_id, Position = "G3", Value = -1 };

                Table table13 = new Table() { TableId = t_id, Position = "A5", Value = 0 };
                Table table14 = new Table() { TableId = t_id, Position = "B4", Value = 0 };
                Table table15 = new Table() { TableId = t_id, Position = "C5", Value = 0 };
                Table table16 = new Table() { TableId = t_id, Position = "D4", Value = 0 };

                Table table17 = new Table() { TableId = t_id, Position = "E5", Value = 0 };
                Table table18 = new Table() { TableId = t_id, Position = "F4", Value = 0 };
                Table table19 = new Table() { TableId = t_id, Position = "G5", Value = 0 };
                Table table20 = new Table() { TableId = t_id, Position = "H4", Value = 0 };

                Table table21 = new Table() { TableId = t_id, Position = "A7", Value = 1 };
                Table table22 = new Table() { TableId = t_id, Position = "C7", Value = 1 };
                Table table23 = new Table() { TableId = t_id, Position = "E7", Value = 1 };
                Table table24 = new Table() { TableId = t_id, Position = "G7", Value = 1 };

                Table table25 = new Table() { TableId = t_id, Position = "B6", Value = 1 };
                Table table26 = new Table() { TableId = t_id, Position = "B8", Value = 1 };
                Table table27 = new Table() { TableId = t_id, Position = "D6", Value = 1 };
                Table table28 = new Table() { TableId = t_id, Position = "D8", Value = 1 };

                Table table29 = new Table() { TableId = t_id, Position = "F6", Value = 1 };
                Table table30 = new Table() { TableId = t_id, Position = "F8", Value = 1 };
                Table table31 = new Table() { TableId = t_id, Position = "H6", Value = 1 };
                Table table32 = new Table() { TableId = t_id, Position = "H8", Value = 1 };
                ctx.SaveChanges();
                ctx.Tables.Add(table);
                ctx.SaveChanges();
                ctx.Tables.Add(table2);
                ctx.SaveChanges();
                ctx.Tables.Add(table3); ctx.Tables.Add(table4);
                ctx.SaveChanges();
                ctx.Tables.Add(table5); ctx.Tables.Add(table6); ctx.Tables.Add(table7); ctx.Tables.Add(table8);
                ctx.Tables.Add(table9); ctx.Tables.Add(table10); ctx.Tables.Add(table11); ctx.Tables.Add(table12);
                ctx.Tables.Add(table13); ctx.Tables.Add(table14); ctx.Tables.Add(table15); ctx.Tables.Add(table16);
                ctx.Tables.Add(table17); ctx.Tables.Add(table18); ctx.Tables.Add(table19); ctx.Tables.Add(table20);
                ctx.Tables.Add(table21); ctx.Tables.Add(table22); ctx.Tables.Add(table23); ctx.Tables.Add(table24);
                ctx.Tables.Add(table25); ctx.Tables.Add(table26); ctx.Tables.Add(table27); ctx.Tables.Add(table28);
                ctx.Tables.Add(table29); ctx.Tables.Add(table30); ctx.Tables.Add(table31); ctx.Tables.Add(table32);
                ctx.SaveChanges();
            }
        }

        private void BeatGame(string t_id)
        {
            using (var ctx = new Context())
            {
                Table table = new Table() { TableId = t_id, Position = "A1", Value = -1 };
                Table table2 = new Table() { TableId = t_id, Position = "A3", Value = -1 };
                Table table3 = new Table() { TableId = t_id, Position = "C1", Value = -1 };
                Table table4 = new Table() { TableId = t_id, Position = "C3", Value = -1 };

                Table table5 = new Table() { TableId = t_id, Position = "B2", Value = -1 };
                Table table6 = new Table() { TableId = t_id, Position = "D2", Value = -1 };
                Table table7 = new Table() { TableId = t_id, Position = "F2", Value = 0 };
                Table table8 = new Table() { TableId = t_id, Position = "H2", Value = -1 };

                Table table9 = new Table() { TableId = t_id, Position = "E1", Value = -1 };
                Table table10 = new Table() { TableId = t_id, Position = "E3", Value = 0 };
                Table table11 = new Table() { TableId = t_id, Position = "G1", Value = -1 };
                Table table12 = new Table() { TableId = t_id, Position = "G3", Value = -1 };

                Table table13 = new Table() { TableId = t_id, Position = "A5", Value = 0 };
                Table table14 = new Table() { TableId = t_id, Position = "B4", Value = 0 };
                Table table15 = new Table() { TableId = t_id, Position = "C5", Value = 1 };
                Table table16 = new Table() { TableId = t_id, Position = "D4", Value = -1 };

                Table table17 = new Table() { TableId = t_id, Position = "E5", Value = 0 };
                Table table18 = new Table() { TableId = t_id, Position = "F4", Value = 0 };
                Table table19 = new Table() { TableId = t_id, Position = "G5", Value = 0 };
                Table table20 = new Table() { TableId = t_id, Position = "H4", Value = 0 };

                Table table21 = new Table() { TableId = t_id, Position = "A7", Value = 1 };
                Table table22 = new Table() { TableId = t_id, Position = "C7", Value = 1 };
                Table table23 = new Table() { TableId = t_id, Position = "E7", Value = 1 };
                Table table24 = new Table() { TableId = t_id, Position = "G7", Value = 1 };

                Table table25 = new Table() { TableId = t_id, Position = "B6", Value = 1 };
                Table table26 = new Table() { TableId = t_id, Position = "B8", Value = 1 };
                Table table27 = new Table() { TableId = t_id, Position = "D6", Value = 0 };
                Table table28 = new Table() { TableId = t_id, Position = "D8", Value = 1 };

                Table table29 = new Table() { TableId = t_id, Position = "F6", Value = 1 };
                Table table30 = new Table() { TableId = t_id, Position = "F8", Value = 1 };
                Table table31 = new Table() { TableId = t_id, Position = "H6", Value = 1 };
                Table table32 = new Table() { TableId = t_id, Position = "H8", Value = 1 };
                ctx.SaveChanges();
                ctx.Tables.Add(table);
                ctx.SaveChanges();
                ctx.Tables.Add(table2);
                ctx.SaveChanges();
                ctx.Tables.Add(table3); ctx.Tables.Add(table4);
                ctx.SaveChanges();
                ctx.Tables.Add(table5); ctx.Tables.Add(table6); ctx.Tables.Add(table7); ctx.Tables.Add(table8);
                ctx.Tables.Add(table9); ctx.Tables.Add(table10); ctx.Tables.Add(table11); ctx.Tables.Add(table12);
                ctx.Tables.Add(table13); ctx.Tables.Add(table14); ctx.Tables.Add(table15); ctx.Tables.Add(table16);
                ctx.Tables.Add(table17); ctx.Tables.Add(table18); ctx.Tables.Add(table19); ctx.Tables.Add(table20);
                ctx.Tables.Add(table21); ctx.Tables.Add(table22); ctx.Tables.Add(table23); ctx.Tables.Add(table24);
                ctx.Tables.Add(table25); ctx.Tables.Add(table26); ctx.Tables.Add(table27); ctx.Tables.Add(table28);
                ctx.Tables.Add(table29); ctx.Tables.Add(table30); ctx.Tables.Add(table31); ctx.Tables.Add(table32);
                ctx.SaveChanges();
            }
        }

        private void KingGame(string t_id)
        {
            using (var ctx = new Context())
            {
                Table table = new Table() { TableId = t_id, Position = "A1", Value = -1 };
                Table table2 = new Table() { TableId = t_id, Position = "A3", Value = -1 };
                Table table3 = new Table() { TableId = t_id, Position = "C1", Value = 0 };
                Table table4 = new Table() { TableId = t_id, Position = "C3", Value = -1 };

                Table table5 = new Table() { TableId = t_id, Position = "B2", Value = 0 };
                Table table6 = new Table() { TableId = t_id, Position = "D2", Value = 1 };
                Table table7 = new Table() { TableId = t_id, Position = "F2", Value = 0 };
                Table table8 = new Table() { TableId = t_id, Position = "H2", Value = -1 };

                Table table9 = new Table() { TableId = t_id, Position = "E1", Value = -1 };
                Table table10 = new Table() { TableId = t_id, Position = "E3", Value = 0 };
                Table table11 = new Table() { TableId = t_id, Position = "G1", Value = -1 };
                Table table12 = new Table() { TableId = t_id, Position = "G3", Value = -1 };

                Table table13 = new Table() { TableId = t_id, Position = "A5", Value = 1 };
                Table table14 = new Table() { TableId = t_id, Position = "B4", Value = -1 };
                Table table15 = new Table() { TableId = t_id, Position = "C5", Value = 0 };
                Table table16 = new Table() { TableId = t_id, Position = "D4", Value = 0 };

                Table table17 = new Table() { TableId = t_id, Position = "E5", Value = 1 };
                Table table18 = new Table() { TableId = t_id, Position = "F4", Value = 0 };
                Table table19 = new Table() { TableId = t_id, Position = "G5", Value = 0 };
                Table table20 = new Table() { TableId = t_id, Position = "H4", Value = 1 };

                Table table21 = new Table() { TableId = t_id, Position = "A7", Value = 1 };
                Table table22 = new Table() { TableId = t_id, Position = "C7", Value = 0 };
                Table table23 = new Table() { TableId = t_id, Position = "E7", Value = 1 };
                Table table24 = new Table() { TableId = t_id, Position = "G7", Value = 1 };

                Table table25 = new Table() { TableId = t_id, Position = "B6", Value = 0 };
                Table table26 = new Table() { TableId = t_id, Position = "B8", Value = 1 };
                Table table27 = new Table() { TableId = t_id, Position = "D6", Value = 0 };
                Table table28 = new Table() { TableId = t_id, Position = "D8", Value = 1 };

                Table table29 = new Table() { TableId = t_id, Position = "F6", Value = 1 };
                Table table30 = new Table() { TableId = t_id, Position = "F8", Value = 1 };
                Table table31 = new Table() { TableId = t_id, Position = "H6", Value = 1 };
                Table table32 = new Table() { TableId = t_id, Position = "H8", Value = 1 };
                ctx.SaveChanges();
                ctx.Tables.Add(table);
                ctx.SaveChanges();
                ctx.Tables.Add(table2);
                ctx.SaveChanges();
                ctx.Tables.Add(table3); ctx.Tables.Add(table4);
                ctx.SaveChanges();
                ctx.Tables.Add(table5); ctx.Tables.Add(table6); ctx.Tables.Add(table7); ctx.Tables.Add(table8);
                ctx.Tables.Add(table9); ctx.Tables.Add(table10); ctx.Tables.Add(table11); ctx.Tables.Add(table12);
                ctx.Tables.Add(table13); ctx.Tables.Add(table14); ctx.Tables.Add(table15); ctx.Tables.Add(table16);
                ctx.Tables.Add(table17); ctx.Tables.Add(table18); ctx.Tables.Add(table19); ctx.Tables.Add(table20);
                ctx.Tables.Add(table21); ctx.Tables.Add(table22); ctx.Tables.Add(table23); ctx.Tables.Add(table24);
                ctx.Tables.Add(table25); ctx.Tables.Add(table26); ctx.Tables.Add(table27); ctx.Tables.Add(table28);
                ctx.Tables.Add(table29); ctx.Tables.Add(table30); ctx.Tables.Add(table31); ctx.Tables.Add(table32);
                ctx.SaveChanges();
            }
        }

        private void WinGame(string t_id)
        {
            using (var ctx = new Context())
            {
                Table table = new Table() { TableId = t_id, Position = "A1", Value = 0 };
                Table table2 = new Table() { TableId = t_id, Position = "A3", Value = 0 };
                Table table3 = new Table() { TableId = t_id, Position = "C1", Value = 0 };
                Table table4 = new Table() { TableId = t_id, Position = "C3", Value = 0 };

                Table table5 = new Table() { TableId = t_id, Position = "B2", Value = 1 };
                Table table6 = new Table() { TableId = t_id, Position = "D2", Value = 0 };
                Table table7 = new Table() { TableId = t_id, Position = "F2", Value = 0 };
                Table table8 = new Table() { TableId = t_id, Position = "H2", Value = 0 };

                Table table9 = new Table() { TableId = t_id, Position = "E1", Value = 0 };
                Table table10 = new Table() { TableId = t_id, Position = "E3", Value = 0 };
                Table table11 = new Table() { TableId = t_id, Position = "G1", Value = 0 };
                Table table12 = new Table() { TableId = t_id, Position = "G3", Value = -1 };

                Table table13 = new Table() { TableId = t_id, Position = "A5", Value = 0 };
                Table table14 = new Table() { TableId = t_id, Position = "B4", Value = 0 };
                Table table15 = new Table() { TableId = t_id, Position = "C5", Value = 0 };
                Table table16 = new Table() { TableId = t_id, Position = "D4", Value = 0 };

                Table table17 = new Table() { TableId = t_id, Position = "E5", Value = 0 };
                Table table18 = new Table() { TableId = t_id, Position = "F4", Value = 1 };
                Table table19 = new Table() { TableId = t_id, Position = "G5", Value = 0 };
                Table table20 = new Table() { TableId = t_id, Position = "H4", Value = 0 };

                Table table21 = new Table() { TableId = t_id, Position = "A7", Value = 0 };
                Table table22 = new Table() { TableId = t_id, Position = "C7", Value = 0 };
                Table table23 = new Table() { TableId = t_id, Position = "E7", Value = 0 };
                Table table24 = new Table() { TableId = t_id, Position = "G7", Value = 0 };

                Table table25 = new Table() { TableId = t_id, Position = "B6", Value = 0 };
                Table table26 = new Table() { TableId = t_id, Position = "B8", Value = 1 };
                Table table27 = new Table() { TableId = t_id, Position = "D6", Value = 0 };
                Table table28 = new Table() { TableId = t_id, Position = "D8", Value = 0 };

                Table table29 = new Table() { TableId = t_id, Position = "F6", Value = 0 };
                Table table30 = new Table() { TableId = t_id, Position = "F8", Value = 0 };
                Table table31 = new Table() { TableId = t_id, Position = "H6", Value = 1 };
                Table table32 = new Table() { TableId = t_id, Position = "H8", Value = 0 };
                ctx.SaveChanges();
                ctx.Tables.Add(table);
                ctx.SaveChanges();
                ctx.Tables.Add(table2);
                ctx.SaveChanges();
                ctx.Tables.Add(table3); ctx.Tables.Add(table4);
                ctx.SaveChanges();
                ctx.Tables.Add(table5); ctx.Tables.Add(table6); ctx.Tables.Add(table7); ctx.Tables.Add(table8);
                ctx.Tables.Add(table9); ctx.Tables.Add(table10); ctx.Tables.Add(table11); ctx.Tables.Add(table12);
                ctx.Tables.Add(table13); ctx.Tables.Add(table14); ctx.Tables.Add(table15); ctx.Tables.Add(table16);
                ctx.Tables.Add(table17); ctx.Tables.Add(table18); ctx.Tables.Add(table19); ctx.Tables.Add(table20);
                ctx.Tables.Add(table21); ctx.Tables.Add(table22); ctx.Tables.Add(table23); ctx.Tables.Add(table24);
                ctx.Tables.Add(table25); ctx.Tables.Add(table26); ctx.Tables.Add(table27); ctx.Tables.Add(table28);
                ctx.Tables.Add(table29); ctx.Tables.Add(table30); ctx.Tables.Add(table31); ctx.Tables.Add(table32);
                ctx.SaveChanges();
            }
        }

        public LoginBIResponse Login(LoginBIRequest request)
        {
            LoginBIResponse response = new LoginBIResponse(-1);
            using (var ctx = new Context())
            {
                var users = ctx.Users.ToList();
                MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
                md5.ComputeHash(ASCIIEncoding.ASCII.GetBytes(request.Password));
                byte[] md5hash = md5.Hash;
                string str = "";
                for (int i = 0; i < md5hash.Length; i++)
                {
                    str = str + (md5hash[i].ToString("x2"));
                }
                var result = ctx.Users.FirstOrDefault(l => l.UserId == request.UserName && l.Password == str);
                if (result != null)
                {
                    response.Code = 101;
                    response.Message = new SuccessCodes().GetSuccessCode(101);
                    result.LoggedIn = true;
                    ctx.SaveChanges();
                }
                else
                {
                    response.Code = 217;
                    response.Message = new ErrorCodes().GetErrorCodes(217);
                }
                var invalidgame = ctx.Games.FirstOrDefault(l => l.Status == 0 && (l.PlayerTwo.UserId == request.UserName || l.PlayerOne.UserId == request.UserName));
                if (invalidgame != null)
                {
                    ctx.Games.Remove(invalidgame);
                    ctx.SaveChanges();
                }
                var ingame = ctx.Games.FirstOrDefault(l => l.Status == 1 && (l.PlayerTwo.UserId == request.UserName || l.PlayerOne.UserId == request.UserName));
                if (ingame != null)
                {
                    response.Table = new Position();
                    Users opponent;
                    Games game = ctx.Games.FirstOrDefault(l => l.PlayerOne.UserId == request.UserName);
                    response.Table = new Position();
                    if (game == null)
                    {
                        game = ctx.Games.FirstOrDefault(l => l.PlayerTwo.UserId == request.UserName);
                        opponent = game.PlayerOne;
                        if (!ingame.FirstPlayerTurn)
                        {
                            response.Table.Turn = true;
                        }
                        else
                        {
                            response.Table.Turn = false;
                        }
                    }
                    else
                    {
                        opponent = game.PlayerTwo;
                        if (ingame.FirstPlayerTurn)
                        {
                            response.Table.Turn = true;
                        }
                        else
                        {
                            response.Table.Turn = false;
                        }
                    }
                    response.Table.Opponent = opponent.UserId;
                    response.Table.TableID = ingame.GameId;

                    var tableResult = ctx.Tables.Where(l => l.TableId == ingame.GameId).ToList();
                    foreach (var item in tableResult)
                    {
                        response.Table.V.Add(item.Value);
                        string pos = item.Position.ToString();
                        response.Table.X.Add(pos[0].ToString());
                        response.Table.Y.Add(pos[1].ToString());
                    }
                }

            }
            return response;
        }

        public LogoutBIResponse Logout(LogoutBIRequest request)
        {
            LogoutBIResponse response = new LogoutBIResponse(-1);
            using (var ctx = new Context())
            {
                var result = ctx.Users.FirstOrDefault(l => (l.UserId == request.UserName) && (l.LoggedIn == true));
                if (result != null)
                {
                    response.Code = 111;
                    response.Message = new SuccessCodes().GetSuccessCode(111);
                    result.LoggedIn = false;
                    ctx.SaveChanges();
                }
            }
            return response;
        }

        public GetMsgBIResponse GetMsg(GetMsgBIRequest request)
        {
            GetMsgBIResponse response = new GetMsgBIResponse(-1);
            using (var ctx = new Context())
            {
                var users = ctx.Users.ToList();
                Users sender;
                Games game = ctx.Games.FirstOrDefault(l => l.PlayerOne.UserId == request.Username);
                if (game == null)
                {
                    game = ctx.Games.FirstOrDefault(l => l.PlayerTwo.UserId == request.Username);
                    sender = game.PlayerOne;
                }
                else
                {
                    sender = game.PlayerTwo;
                }
                var result = ctx.ChatDiaries.Where(l => l.NewMessage == true && l.Player.UserId == sender.UserId && l.TableId == request.TableId).ToList();
                if (result != null)
                {
                    response.ChatMessage = new List<string>();
                    ctx.SaveChanges();
                    response.Code = 105;
                    response.Message = new SuccessCodes().GetSuccessCode(105);
                    foreach (var item in result)
                    {
                        response.ChatMessage.Add(item.Message);
                        item.NewMessage = false;
                    }
                    ctx.SaveChanges();
                }
                else
                {
                    response.Code = 212;
                    response.Message = new ErrorCodes().GetErrorCodes(212);
                }

            }
            return response;
        }

        public CloseGameBIResponse CloseGame(CloseGameBIRequest request)
        {
            CloseGameBIResponse response = new CloseGameBIResponse(-1);
            using (var ctx = new Context())
            {
                var users = ctx.Users.ToList();
                var result = ctx.Games.FirstOrDefault(l => (l.Status < 2) && (l.GameId == request.TableID));
                if (result != null)
                {
                    result.Status = 2;
                    ctx.SaveChanges();

                    response.Code = 110;
                    response.Message = new SuccessCodes().GetSuccessCode(110);
                }
            }
            return response;
        }

        public GiveUpBIResponse GiveUp(GiveUpBIRequest request)
        {
            GiveUpBIResponse response = new GiveUpBIResponse(-1);
            using (var ctx = new Context())
            {
                var users = ctx.Users.ToList();
                Users player;
                Users opponent;
                Games game = ctx.Games.FirstOrDefault(l => l.PlayerOne.UserId == request.UserID);
                if (game == null)
                {
                    game = ctx.Games.FirstOrDefault(l => l.PlayerTwo.UserId == request.UserID);
                    opponent = game.PlayerOne;
                    player = game.PlayerTwo;
                }
                else
                {
                    opponent = game.PlayerTwo;
                    player = game.PlayerOne;
                }

                var result = ctx.Games.FirstOrDefault(l => (l.Status == 1) && (l.GameId == request.TableID));
                if (result != null)
                {
                    result.Status = 2;

                    player.Loss++;
                    opponent.Win++;

                    int[] eloPoints = EloComputing(opponent.ELO, player.ELO);
                    player.ELO = eloPoints[1];
                    opponent.ELO = eloPoints[0];

                    ctx.SaveChanges();
                    response.Opponent = opponent.UserId;
                    response.Code = 107;
                    response.Message = new SuccessCodes().GetSuccessCode(107);
                }
            }
            return response;
        }

        private int[] EloComputing(int winerUser, int loserUser)
        {

            int eloChange = ((Math.Abs(winerUser - loserUser) > 200) ? 0 : 100 - Math.Abs(winerUser - loserUser) / 2);
            int[] ret = new int[] { winerUser + eloChange, loserUser - eloChange };

            return ret;
        }

        public JoinGameBIResponse JoinGame(JoinGameBIRequest request)
        {
            JoinGameBIResponse response = new JoinGameBIResponse(-1);
            using (var ctx = new Context())
            {
                var result = ctx.Games.FirstOrDefault(l => (l.Status == 0) && (l.GameId == request.TableID));
                if (result != null)
                {
                    var users = ctx.Users.ToList();
                    var user = ctx.Users.FirstOrDefault(l => l.UserId == request.UserName);
                    result.PlayerTwo = user;
                    result.Status = 1;
                    ctx.SaveChanges();

                    if (WaitingUsers.Contains(result.PlayerOne.UserId))
                    {
                        WaitingUsers.RemoveAt(WaitingUsers.IndexOf(result.PlayerOne.UserId));
                    }

                    response.Opponent = result.PlayerOne.UserId;
                    response.Code = 103;
                    response.Message = new SuccessCodes().GetSuccessCode(103);
                }
            }
            return response;
        }

        public ListGameBIResponse ListGame(ListGameBIRequest request)
        {
            ListGameBIResponse response = new ListGameBIResponse(-1);
            using (var ctx = new Context())
            {
                var users = ctx.Users.ToList();
                var result = ctx.Games.Where(l => (l.Status == 0));
                if (result != null)
                {
                    response.Games = new List<Entity.Game>();
                    foreach (var item in result)
                    {
                        response.Games.Add(new Entity.Game() { GameId = item.GameId, PlayerOne = item.PlayerOne.UserId, PlayerTwo = item.PlayerTwo.UserId, Status = 0 });
                    }

                    response.Code = 112;
                    response.Message = new SuccessCodes().GetSuccessCode(112);

                }
            }
            return response;
        }

        public NewGameBIResponse NewGame(NewGameBIRequest request)
        {
            NewGameBIResponse response = new NewGameBIResponse(-1);
            using (var ctx = new Context())
            {
                var result = ctx.Users.FirstOrDefault(l => (l.UserId == request.Username) && (l.LoggedIn == true));

                Games new_game = new Games { LastMove = DateTime.Now, Status = 0, PlayerTwo = result, PlayerOne = result, GameId = Convert.ToString(gameNumber++), FirstPlayerTurn = true };
                ctx.Games.Add(new_game);
                ctx.SaveChanges();
                var game_id = ctx.Games.Where(l => l.PlayerOne.UserId == request.Username && l.Status == 0).ToList();
                NewEmptyGame(new_game.GameId);
                WaitingUsers.Add(request.Username);
                response.Code = 104;
                response.Message = new SuccessCodes().GetSuccessCode(104);
                response.TableID = game_id[0].GameId;
            }
            return response;
        }

        public PlayerStatsBIResponse PlayerStats(PlayerStatsBIRequest request)
        {
            PlayerStatsBIResponse response = new PlayerStatsBIResponse(-1);
            using (var ctx = new Context())
            {
                var result = ctx.Users.FirstOrDefault(l => (l.UserId == request.OpponentUsername));

                response.Draw = result.Draw;
                response.ELO = result.ELO;
                response.Level = result.Level;
                response.Loss = result.Loss;
                response.Win = result.Win;

                response.Code = 113;
                response.Message = new SuccessCodes().GetSuccessCode(113);


            }
            return response;
        }


        public RegistrationBIResponse Registration(RegistrationBIRequest request)
        {
            RegistrationBIResponse response = new RegistrationBIResponse(-1);
            using (var ctx = new Context())
            {

                var result = ctx.Users.FirstOrDefault(l => (l.UserId == request.Username));
                if (result != null && request.Username != "Guest")
                {
                    response.Code = 200;
                    response.Message = new ErrorCodes().GetErrorCodes(200);
                }
                else
                {
                    string regname = request.Username;
                    Users user;
                    /*if (request.Username == "Guest")
                    {
                        regname = request.Username + "_" + Convert.ToString(guestNumber);
                        user = new Users() { UserId = regname, Password = request.Password, Draw = 0, ELO = 1200, Email = request.EmailAddress, Level = 0, LoggedIn = true, Loss = 0, Win = 0 };

                    }
                    else
                    {*/
                    if (request.Username == "Guest")
                    {
                        regname = request.Username + "_" + Convert.ToString(guestNumber);
                    }
                    MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
                    md5.ComputeHash(ASCIIEncoding.ASCII.GetBytes(request.Password));
                    byte[] md5hash = md5.Hash;
                    StringBuilder str = new StringBuilder();
                    for (int i = 0; i < md5hash.Length; i++)
                    {
                        str.Append(md5hash[i].ToString("x2"));
                    }
                    user = new Users() { UserId = regname, Password = str.ToString(), Draw = 0, ELO = 1200, Email = request.EmailAddress, Level = 0, LoggedIn = false, Loss = 0, Win = 0 };
                    //}

                    ctx.Users.Add(user);
                    ctx.SaveChanges();
                    if (request.Username == "Guest")
                        response.Code = guestNumber++;
                    else
                        response.Code = 100;
                    response.Message = new SuccessCodes().GetSuccessCode(100);
                }
            }
            return response;
        }

        public SendMsgBIResponse SendMsg(SendMsgBIRequest request)
        {
            SendMsgBIResponse response = new SendMsgBIResponse(-1);
            using (var ctx = new Context())
            {
                var users = ctx.Users.ToList();
                Users opponent;
                Games game = ctx.Games.FirstOrDefault(l => l.PlayerOne.UserId == request.UserName);
                if (game == null)
                {
                    game = ctx.Games.FirstOrDefault(l => l.PlayerTwo.UserId == request.UserName);
                    opponent = game.PlayerOne;
                }
                else
                {
                    opponent = game.PlayerTwo;
                }

                var result = ctx.Users.FirstOrDefault(l => (l.UserId == request.UserName));
                ctx.ChatDiaries.Add(new ChatDiary() { Message = request.Message, Player = result, TableId = request.TableID, NewMessage = true });
                ctx.SaveChanges();
                response.Username = opponent.UserId;
                response.Code = 106;
                response.Message = new SuccessCodes().GetSuccessCode(106);
            }
            return response;
        }

        public StepBIResponse Step(StepBIRequest request, StepBIResponse response)
        {
            using (var ctx = new Context())
            {
                var result = ctx.Users.FirstOrDefault(l => (l.UserId == request.UserID) && (l.LoggedIn == true));
                if (result != null)
                {
                    var users = ctx.Users.ToList();
                    Users opponent;
                    Games game = ctx.Games.FirstOrDefault(l => l.PlayerOne.UserId == request.UserID);
                    if (game == null)
                    {
                        game = ctx.Games.FirstOrDefault(l => l.PlayerTwo.UserId == request.UserID);
                        opponent = game.PlayerOne;
                    }
                    else
                    {
                        opponent = game.PlayerTwo;
                    }
                    Games valid = ctx.Games.FirstOrDefault(l => l.Status == 1 && l.GameId == request.TableID);
                    if (valid != null)
                    {
                        Table start = (from x in ctx.Tables
                                       where (x.Position == request.StepFrom.X + request.StepFrom.Y) && (x.TableId == request.TableID)
                                       select x).FirstOrDefault();
                        int actualValue = start.Value;
                        start.Value = 0;
                        Table dest = (from x in ctx.Tables
                                      where (x.Position == request.StepTo.X + request.StepTo.Y) && (x.TableId == request.TableID)
                                      select x).FirstOrDefault();
                        dest.Value = actualValue;

                        var turn_change = ctx.Games.FirstOrDefault(l => l.GameId == request.TableID && ((l.PlayerOne.UserId == request.Opponent) || (l.PlayerTwo.UserId == request.Opponent) || (l.PlayerOne.UserId == request.UserID) || (l.PlayerTwo.UserId == request.UserID)));
                        turn_change.FirstPlayerTurn = !turn_change.FirstPlayerTurn;
                        response.Code = 108;
                        response.Message = new SuccessCodes().GetSuccessCode(108);
                        ctx.Diaries.Add(new Diary() { Turn = request.FirstPlayer, LastMove = DateTime.Now, Color = request.FirstPlayer, Move = (request.StepFrom.X + request.StepFrom.Y + "-" + request.StepTo.X + request.StepTo.Y), Player = result, TableId = request.TableID });


                        if (request.StepTo.Y == "1" && request.FirstPlayer)
                        {
                            dest.Value = 2;
                            response.Code = 109;
                            response.Message = new SuccessCodes().GetSuccessCode(109);
                        }
                        else if (request.StepTo.Y == "8" && !request.FirstPlayer)
                        {
                            dest.Value = -2;
                            response.Code = 109;
                            response.Message = new SuccessCodes().GetSuccessCode(109);
                        }

                        var pieces = ctx.Tables.Where(l => l.TableId == request.TableID).ToList();
                        if (request.FirstPlayer)
                        {
                            bool over = true;
                            foreach (var item in pieces)
                            {
                                if (item.Value == -1)
                                    over = false;
                            }
                            if (over)
                            {
                                response.Code = 115;
                                response.Message = new SuccessCodes().GetSuccessCode(115);

                            }
                        }
                        else
                        {
                            bool over = true;
                            foreach (var item in pieces)
                            {
                                if (item.Value == 1)
                                    over = false;
                            }
                            if (over)
                            {
                                response.Code = 115;
                                response.Message = new SuccessCodes().GetSuccessCode(115);

                            }
                        }

                        response.Opponent = opponent.UserId;
                    }
                    else
                    {
                        response.Code = 213;
                        response.Message = new ErrorCodes().GetErrorCodes(213);
                    }


                    if (response.Code == 115)
                    {
                        result.Win++;
                        opponent.Loss++;
                        int[] eloPoints = EloComputing(result.ELO, opponent.ELO);
                        result.ELO = eloPoints[0];
                        opponent.ELO = eloPoints[1];
                    }
                    ctx.SaveChanges();
                }
            }

            return response;
        }

        #region Checking datas

        public bool IsLogged(string Username)
        {
            bool logged = false;
            using (var ctx = new Context())
            {
                var result = ctx.Users.FirstOrDefault(l => (l.UserId == Username));
                if (result == null)
                {
                    return logged;
                }
                logged = result.LoggedIn;
            }
            return logged;
        }

        public bool IsGameAlive(string ID)
        {
            bool alive = false;
            using (var ctx = new Context())
            {
                var result = ctx.Games.FirstOrDefault(l => l.GameId == ID);
                if (result != null)
                    alive = true;
            }
            return alive;
        }

        public bool IsThereNewMsg(string TableID)
        {
            bool is_new = false;
            using (var ctx = new Context())
            {
                var result = ctx.ChatDiaries.FirstOrDefault(l => l.TableId.Contains(TableID) && l.NewMessage == true);
                if (result != null)
                    is_new = true;
                else
                    is_new = false;
            }
            return is_new;
        }

        public bool IsProperTable(string TableID, string Username)
        {
            bool proper = false;
            using (var ctx = new Context())
            {
                var result = ctx.Games.FirstOrDefault(l => l.GameId == TableID && (l.PlayerOne.UserId == Username || l.PlayerTwo.UserId == Username));
                if (result != null)
                    proper = true;
                else
                    proper = false;
            }
            return proper;
        }

        public bool IsSameLevel(string TableID, string Username)
        {
            bool same = false;
            using (var ctx = new Context())
            {
                var users = ctx.Users.ToList();
                var user = ctx.Users.FirstOrDefault(l => l.UserId == Username);
                var result = ctx.Games.FirstOrDefault(l => l.GameId == TableID);
                if (user.Level == result.PlayerOne.Level)
                    same = true;
                else
                    same = false;
            }
            return same;
        }

        /*public  bool IsThereSameLevel(string Username)
        {
            bool same = false;
            using (var ctx = new Context())
            {
                var user = ctx.Users.FirstOrDefault(l => l.UserId == Username);
                var games = ctx.Games.FirstOrDefault(l => l.PlayerOne.Level == user.Level);
                if (games != null)
                    same = true;
                else
                    same = false;
            }
            return same;
        }*/

        public bool IsDatasValid(string Username)
        {
            bool valid = false;


            using (var ctx = new Context())
            {
                var user = ctx.Users.FirstOrDefault(l => l.UserId == Username);
                if (user == null)
                    valid = true;
                else
                    valid = false;
            }

            return valid;
        }

        public bool IsKill(StepBIRequest request, StepBIRequest check)
        {
            bool success = false;
            using (var ctx = new Context())
            {
                var result = ctx.Tables.FirstOrDefault(l => l.TableId == request.TableID && l.Position == (request.StepFrom.X + request.StepFrom.Y).ToString());
                var killed = ctx.Tables.FirstOrDefault(l => l.TableId == request.TableID && l.Position == (check.StepFrom.X + check.StepFrom.Y).ToString());
                Table kill = (from x in ctx.Tables
                              where (x.Position == (check.StepTo.X + check.StepTo.Y)) && (x.TableId == request.TableID)
                              select x).FirstOrDefault();
                kill.Value = 0;
                ctx.SaveChanges();
                success = true;
            }
            return success;
        }

        public bool IsKing(StepBIRequest request)
        {
            bool isKing = false;
            using (var ctx = new Context())
            {
                var result = ctx.Tables.FirstOrDefault(l => l.TableId == request.TableID && l.Position == (request.StepFrom.X + request.StepFrom.Y).ToString());
                if (result != null)
                    if (Math.Abs(result.Value) == 2)
                        isKing = true;
            }
            return isKing;
        }

        public bool IsEnemy(StepBIRequest request, bool color)
        {
            bool isEnemy = false;
            using (var ctx = new Context())
            {
                var result = ctx.Tables.FirstOrDefault(l => l.TableId == request.TableID && l.Position == (request.StepFrom.X + request.StepFrom.Y).ToString());
                if (result != null)
                {
                    if (result.Value < 0 && !color)
                    {
                        isEnemy = true;
                    }
                    else if (result.Value > 0 && color)
                    {
                        isEnemy = true;
                    }
                    else
                    {
                        isEnemy = false;
                    }
                }
            }
            return isEnemy;
        }

        public bool IsReserved(StepBIRequest request)
        {
            bool reserved = false;
            using (var ctx = new Context())
            {
                var result = ctx.Tables.FirstOrDefault(l => l.Position == (request.StepTo.X + request.StepTo.Y).ToString() && l.TableId == request.TableID);
                if (result != null)
                    if (result.Value != 0)
                        reserved = true;
            }
            return reserved;
        }

        public bool Turn(StepBIRequest request)
        {
            bool turn = false;
            using (var ctx = new Context())
            {
                var result = ctx.Games.FirstOrDefault(l => l.GameId == request.TableID);
                if (result != null)
                    if (result.FirstPlayerTurn == request.FirstPlayer)
                        turn = true;
            }
            return turn;
        }

        #endregion

        public bool IsInGame(string request)
        {
            bool ingame = false;
            using (var ctx = new Context())
            {
                var result = ctx.Games.FirstOrDefault(l => (l.PlayerOne.UserId == request || l.PlayerTwo.UserId == request) && l.Status == 1);
                if (result != null)
                    ingame = true;
            }
            return ingame;
        }

    }
}
